iT邦幫忙

2022 iThome 鐵人賽

DAY 9
0
Modern Web

web component - 次世代網頁技術的重要拼圖系列 第 9

[Day8] web component的使用技巧-shadow DOM存取其一

  • 分享至 

  • xImage
  •  

鐵人賽開始也快過了三分之一了,回頭看了自己的文章,寫的還真是亂。這個星期六日有時間的話會把前面的文章再整理一下。

從這篇文章開始,會著重在解決前一篇文章所提到的各種web component的問題(以單一專案的小範圍開發為前提)。

一個完整的web componet(custom element + shadow DOM)最主要的目的就是要讓component的內外分離。所以外部無法直接存取或控制component內部的DOM(因為document.getElementById 之類的方法無法獲取web component內部的DOM)。

幸好,custom element是javascript和HTML element的結合,再加上shadow DOM的特性。可以使用以下的方法來改變內部的DOM。

間接的方法

在普通的HTML 元素中,

使用web component 的屬性來設定Shadow DOM

因為web component是使用custom element技術來建立,所以普通的HTML元素會有的屬性也可以在web component上使用。只要使用getAttribute這個方法就能獲得指定的屬性值

屬性的觀察者模式

需要使用 custom element 生命周期的observedAttributes設定監看的屬性值,以及使用生命周期的attributeChangedCallback來改動Shadow DOM。

使用web component 的方法

因為 web component 有使用到javascript,所以也可以使用javascript的方法來改動Shadow DOM。

例子

html

<-- 只有設定'card-content'這個屬性 -->
<my-com id="my-com" card-content="ha! you~"></my-com>

Javascript

class MyComponent extends HTMLElement {
    constructor() {
        super();
        this.render = this.render.bind(this);
        this.attachShadow({mode: 'open'});
        this.shadowRoot.appendChild(this.render())
    }
    connectedCallback() {
    }
    static get observedAttributes() {
        // 只有'card-content'這個屬性要監看變化
        return ['card-content'];
    }
    attributeChangedCallback(name, oldValue, newValue) {
        // 當'card-content'這個屬性變化時使用
        if (name === 'card-content') {
            this.shadowRoot.getElementById('card-content').innerHTML = newValue;
        }
    }
    set cardContent(value) {
        // 如果有和屬性連動的話,建議只改屬性值,實際的變化留到attributeChangedCallback中再修改
        this.setAttribute('card-content', value);
    }
    get cardContent() {
        return this.getAttribute('card-content');
    }
    set cardTitle(value) {
        // 因為沒有和屬性連動的話,可以直接變動shadow DOM
        this.shadowRoot.getElementById('card-title').innerHTML = value;
    }
    get cardTitle() {
        return this.shadowRoot.getElementById('card-title').innerHTML;
    }
    render() {
        const template = document.createElement('template');
        template.innerHTML = `
            <div>
                <h2 id='card-title'>title</h2>
                <div id='card-content'></div>
            </div>
        `;
        return template.content;
    }
}
customElements.define('my-com', MyComponent);
const myComNode = document.getElementById('my-com');
console.log(myComNode.cardContent) //ha! you~
console.log(myComNode.cardTitle) //title
myComNode.cardContent = 'hallo world'
myComNode.cardTitle = 'Title2'
console.log(myComNode.cardContent) //hallo world
console.log(myComNode.cardTitle) //Title2

上一篇
[Day7] shadow DOM 的使用和問題
下一篇
[Day9] web component的使用技巧-shadow DOM存取其二
系列文
web component - 次世代網頁技術的重要拼圖30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言